Skip to content

Conversation

trcazier
Copy link

@trcazier trcazier commented Oct 1, 2025

No description provided.

@robodoo
Copy link

robodoo commented Oct 1, 2025

Pull request status dashboard

@trcazier trcazier force-pushed the 19.0-tutorial-industry-trcaz branch from 7ee5e1f to 4b5f71c Compare October 1, 2025 07:39
[IMP] estate: add chapter 2

[IMP] estate: add chapter 3

[IMP] estate: add chapter 4

[IMP] estate: add chapter 5

[IMP] estate: add chapter 6

[IMP] estate: (chapter 7) add types, tags, & offers views/models and fix search group by & menu names

[IMP] estate: add chapter 8

[IMP] estate: Chapter 10

[IMP] estate: add Chapter 11

[IMP] estate: apply some of Faruk's suggestions from the PR

[IMP] estate: remove superfluous encoding line (runbot)

[IMP] estate: add _ to UserError string parameters

[IMP] estate: add chapter 12

[IMP] estate: fix the default date availability being computed only on upgrade

[ADD] estate_account: add module manifest

[IMP] estate: fix the default date lambda parameter error

[IMP] estate_account: add chapter 13

[IMP] estate: add chapter 14

[IMP] estate, estate_account: fix author and license warning

[IMP] estate: apply some PR suggestions

[IMP] estate: prefix ondelete method with _unlink

Co-authored-by: Cemal Faruk Güney <[email protected]>

[IMP] estate: apply R&D string convention

[IMP] estate: apply PR suggestions

[IMP] estate_account: make action_property_sold more extensible and maintainable

[IMP] estate, estate_account: implement tests and fix code to pass them

[IMP] estate: implement test for garden uncheck behavior

[IMP] estate: change test class names according to the conventions

[IMP] estate: change references to self.properties[i] to their own variables for clarity

[IMP] estate: change import style

Co-authored-by: Cemal Faruk Güney <[email protected]>

[IMP] estate: apply PR suggestions

[IMP] estate: make test imports clean and not relative

[IMP] estate_account: add test to check account.move creation on sell

[IMP] estate_account: make test more robust by sorting invoice lines according to price

[IMP] *: add empty tutorial commit
@trcazier trcazier force-pushed the 19.0-tutorial-industry-trcaz branch from f77cd91 to bdb9f65 Compare October 2, 2025 12:38
Copy link

@abdrahmanrashed abdrahmanrashed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great job, just some small things and you are good to go

<record id="api_public_write_rule" model="ir.rule">
<field name="name">Public users can't write</field>
<field name="model_id" ref="real_estate_property_model"/>
<field name="domain_force">[(0, '=', 1)]</field>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the purpose of this rule?
the domain is false for all instances right?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the tutorial said to allow read and write on the route (to allow the server action to be executed), but restrict the write user access with this domain

add an access right record to allow public users to read and write the model

prevent any write from the public user by adding a record rule for the write operation with an impossible domain (e.g. [('id', '=', False)])

<field name="x_bedrooms"/>
<field name="x_living_area"/>
<field name="x_expected_price"/>
<field name="x_date_availability" optional="disabled"/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this set a disabled?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excellent question

Copy link

@vava-odoo vava-odoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done. Just a few comments reading through the xml part. Don't hesitate to let me know if anything is unclear

{
'name': 'Estate (import)',
'depends': [
'base',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every module depends on base, so base is only mentioned if there is no other.

Suggested change
'base',

<field name="name">x_garden_orientation</field>
<field name="field_description">Garden Orientation</field>
<field name="ttype">selection</field>
<field name="selection">[('x_north', "North"), ('x_south', "South"), ('x_east', "East"), ('x_west', "West")]</field>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't it asked to use ir.model.fields.selection?

<field name="model_id" ref="real_estate_property_model" />
<field name="name">x_total_area</field>
<field name="field_description">Total Area</field>
<field name="ttype">float</field>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes not much sense, but since other areas are integers, this one should be an integer as well


<!-- Actions -->

<record id="api_public_write_rule" model="ir.rule">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you have a security folder, this record should be there

<field name="model">x_estate.property</field>
</record>

<record model="ir.model.access" id="access_real_estate_property_public">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, should be in security/

Comment on lines +16 to +17
<field name="selection">True</field>
<field name="selection">[('x_accepted', "Accepted"), ('x_refused', "Refused")]</field>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it makes no sense to define twice the same field (only last one is taken into account)

<field name="ttype">many2one</field>
<field name="relation">res.partner</field>
<field name="required">True</field>
<field name="on_delete">cascade</field>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a bit 🤠 but fine

<field name="name">x_estate.property.offer.view.list</field>
<field name="model">x_estate.property.offer</field>
<field name="arch" type="xml">
<list string="Property offer list test string?">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👀

<field name="name">Property types</field>
<field name="res_model">x_estate.property.type</field>
<field name="view_mode">list</field>
<field name="context">{'search_default_available': True}</field>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work?

<field name="name">Property tags</field>
<field name="res_model">x_estate.property.tag</field>
<field name="view_mode">list</field>
<field name="context">{'search_default_available': True}</field>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work?

Copy link

@vava-odoo vava-odoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went on and read your whole code. Overall super good, just noted a few things.
No need to update anything here, just food for thought

@@ -0,0 +1,5 @@
"id","name","sequence","property_ids","offer_ids","offer_count"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I bet you don't have to list all fields, only the one you define (and the required ones, obviously)

<record id="property_1" model="estate.property">
<field name="name">Big Villa</field>
<field name="property_type_id" ref="property_type_1"/>
<field name="state">new</field>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default value, not necessary

Suggested change
<field name="state">new</field>

def _unlink_check_status(self):
for record in self:
if record.state not in ['new', 'cancelled']:
raise UserError(_("A property can only be deleted if its state is 'New' or 'Cancelled'"))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We try to have less technical messages for end-users, something like

Suggested change
raise UserError(_("A property can only be deleted if its state is 'New' or 'Cancelled'"))
raise UserError(_("A property can only be deleted if it is a new one or if it was cancelled."))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also note that _() has been mostly replaced by self.env._()

Comment on lines +85 to +86
if not record.offer_ids:
raise UserError(_("A property with no offers cannot be sold."))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it too constraining the end user? You probably have specific cases where you want to bypass the "normal" flow and such conditions could be a burden for some users

Comment on lines +3 to +4
from odoo import _, api, exceptions, fields, models
from odoo.exceptions import UserError

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from odoo import _, api, exceptions, fields, models
from odoo.exceptions import UserError
from odoo import _, api, fields, models
from odoo.exceptions import UserError

<field name="bedrooms" />
<field name="living_area" filter_domain="[('living_area', '&gt;=', self)]"/>
<field name="facades" />
<filter name="available" string="Available" domain="['|', ('state', '=', 'new'), ('state', '=', 'offer_received')]"/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shorter (and maybe clearer) this way

Suggested change
<filter name="available" string="Available" domain="['|', ('state', '=', 'new'), ('state', '=', 'offer_received')]"/>
<filter name="available" string="Available" domain="[('state', 'in', ['new', 'offer_received'])]"/>

} for record in self]

def action_property_sold(self):
invoice_vals = self.get_sold_property_invoice_values()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice way to do it


def action_property_sold(self):
invoice_vals = self.get_sold_property_invoice_values()
self.env['account.move'].create(invoice_vals)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fear you need a sudo here, as not all you sellers will be able to create an invoice

Comment on lines +13 to +14
self.invoice = self.env['account.move'].search(Domain('partner_id', '=', self.cozy_cottage.buyer_id.id) & Domain('move_type', '=', 'out_invoice'))
self.assertTrue(self.invoice)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you only need to check the existence, use search_count with limit=1 (if you need the first record, then only limit=1)

self.invoice = self.env['account.move'].search(Domain('partner_id', '=', self.cozy_cottage.buyer_id.id) & Domain('move_type', '=', 'out_invoice'))
self.assertTrue(self.invoice)

sorted_invoice_lines = self.invoice.invoice_line_ids.sorted(key=lambda r: r.price_unit)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the price of the house is really small? 🙃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants